package com.huishi.util;

import com.huishi.entity.vo.FileMetaDataVO;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
public class FileUtils {

    public static boolean deleteFile(String filePath) {
        return new File(filePath).delete();
    }

    /**
     * 删除目录下的所有文件和子目录
     *
     * @param directory 目录
     */
    public static void deleteDirectoryContents(File directory) {

        if (directory.exists() && directory.isDirectory()) {
            // 获取目录下的所有文件和子目录
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    // 如果是目录，则递归删除目录内容
                    if (file.isDirectory()) {
                        deleteDirectoryContents(file);
                    }
                    // 删除文件或空目录
                    if (!file.delete()) {
                        log.error("无法删除文件或目录: " + file.getAbsolutePath());
                    }
                }
            }
            directory.delete();
            log.info("文件删除成功");
        } else log.info("目录不存在或者不是一个目录");
    }

    /**
     * 获取当前绝对路径
     *
     * @return
     */
    public static String getCurrentAbsolutePath() {
        // 获取当前工作目录
        String currentPath = System.getProperty("user.dir");
        System.out.println(currentPath);

        // 创建 File 对象并获取绝对路径
        File file = new File(currentPath);

        return file.getAbsolutePath();
    }

    /**
     * 创建文件夹
     *
     * @param folderPath
     */
    public static void createFolder(String folderPath) {
        File folder = new File(folderPath);

        if (!folder.exists()) {
            if (folder.mkdirs()) log.info("文件夹创建成功：{}", folderPath);
            else log.info("文件夹创建失败：{}", folderPath);
        } else log.info("文件夹已存在：{}", folderPath);
    }

    /**
     * 格式化文件大小
     *
     * @param size
     * @return
     */
    public static String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B"; // 小于1KB，显示为字节
        } else if (size < 1024 * 1024) {
            return String.format("%.2f", (double) size / 1024) + " KB"; // 小于1MB，显示为KB
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f", (double) size / (1024 * 1024)) + " MB"; // 小于1GB，显示为MB
        } else if (size < 1024L * 1024 * 1024 * 1024) {
            return String.format("%.2f", (double) size / (1024 * 1024 * 1024)) + " GB"; // 小于1TB，显示为GB
        } else {
            return String.format("%.2f", (double) size / (1024L * 1024 * 1024 * 1024)) + " TB"; // 显示为TB
        }
    }

    /**
     * 根据文件夹目录返回文件绝对路径list
     * <p>
     * 过滤后缀：
     * 如果系统型号对应的文件数据后缀是dat和pls，不是这两个后缀的文件不上传，
     * 而且文件名(不包含后缀)一样的一组dat和pls少一个也不要上传。
     *
     * @param directoryPath  文件目录
     * @param fileMetaDataVO 文件元数据
     * @return
     * @throws IOException
     */
    public static Map<String, Object> getAllFilesInDirectory(Path directoryPath, FileMetaDataVO fileMetaDataVO) throws IOException {
        // 系统对应的数据文件后缀
        String dataFormat = fileMetaDataVO.getSystemModel().getDataFormat();
        List<String> dataSuffix = Arrays.stream(dataFormat.replace("[", "").replace("]", "").split(","))
                .map(String::trim) // 去掉每个元素的前后空格
                .toList();


        Map<String, Object> result = new HashMap<>();
        List<Path> filePaths;
        long totalSize = 0;
        String dirPath = fileMetaDataVO.getDirPath();
        if (new File(dirPath).isFile()) { // 单个文件
            filePaths = new ArrayList<>();

            String extension = "";
            int dotIndex = dirPath.lastIndexOf('.');
            if (dotIndex > 0 && dotIndex < dirPath.length() - 1) {
                extension = dirPath.substring(dotIndex + 1);
            }

            if (dataSuffix.contains(extension)) {
                Path filePath = Path.of(dirPath);
                filePaths.add(filePath);
                totalSize = filePath.toFile().length();
            }
        } else {// 文件夹
            // 使用 Files.walk 方法来遍历文件夹及其子目录中的文件。
            // Integer.MAX_VALUE 用于设置遍历深度，FileVisitOption.FOLLOW_LINKS 表示要遵循符号链接。
            try (Stream<Path> stream = Files.walk(directoryPath, Integer.MAX_VALUE, FileVisitOption.FOLLOW_LINKS)) {
                filePaths = stream
                        .filter(path -> Files.isRegularFile(path) && hasMatchingSuffix(path, dataSuffix)) // 过滤后缀是指定后缀的文件
                        .collect(Collectors.toList());

                // Map保存文件名（不含后缀），并保存不同后缀的文件路径
                Map<String, List<Path>> fileGroups = new HashMap<>();
                for (Path path : filePaths) {
                    String fileNameWithoutSuffix = getFileNameWithoutSuffix(path);
                    fileGroups.computeIfAbsent(fileNameWithoutSuffix, k -> new ArrayList<>()).add(path);
                }

                // 过滤只包含所有指定后缀成对出现的文件
                filePaths = fileGroups.values().stream()
                        .filter(list -> containsAllSuffixes(list, dataSuffix)) // 确保所有指定后缀都存在
                        .flatMap(List::stream)
                        .toList();

                totalSize = filePaths.stream()
                        .filter(Files::isRegularFile)
                        .mapToLong(path -> {
                            try {
                                return Files.size(path);
                            } catch (IOException e) {
                                // 处理获取文件大小时的异常
                                e.printStackTrace();
                                return 0; // 返回 0 或者其他默认值，取决于你的需求
                            }
                        })
                        .sum();
            } catch (IOException e) {
                throw new IOException("遍历目录时发生错误: " + e.getMessage(), e);
            }
        }
        result.put("files", filePaths);
        result.put("fileTotalSize", totalSize);
        return result;
    }

    // 检查文件是否包含指定的后缀之一
    private static boolean hasMatchingSuffix(Path path, List<String> extensions) {
        return extensions.stream().anyMatch(extension -> path.toString().endsWith(extension));
    }

    // 获取文件名（去除后缀部分）
    private static String getFileNameWithoutSuffix(Path path) {
        String fileName = path.getFileName().toString();
        int dotIndex = fileName.lastIndexOf(".");
        return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
    }

    // 确保文件列表中包含所有指定的后缀
    private static boolean containsAllSuffixes(List<Path> files, List<String> suffixes) {
        Set<String> fileExtensions = files.stream()
                .map(path -> path.toString().substring(path.toString().lastIndexOf(".") + 1)) // 获取文件后缀
                .collect(Collectors.toSet());
        return fileExtensions.containsAll(suffixes); // 检查是否包含所有指定的后缀
    }
}
